#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <iostream>
#include "header/triangle_v2.hpp"

const float TriangleV2::vertices[] = {
    0.0f, 0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    -0.5f, -0.5f, 0.0f
};

int TriangleV2::createShader(int type, const char* source){
    int shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    int success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[520];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::COMPILATION_FAILED\n" << std::endl;
        return 0;
    }
    return shader;
}

int TriangleV2::createProgram(){
    int vertexShader = createShader(GL_VERTEX_SHADER, vertex_shader_code);
    int fragmentShader = createShader(GL_FRAGMENT_SHADER, fragment_shader_code);

    if (!vertex_shader_code || !fragment_shader_code) {
        return 0;
    }
    uint32_t program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    int success;
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success) {
        char logInfo[512];
        glGetProgramInfoLog(program, 512, NULL, logInfo);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<< logInfo << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return program;
}

bool TriangleV2::init(){
    mProgram = createProgram();
    if (!mProgram){
        return false;
    }
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //glGetAttribLocation
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    return true;
}

void TriangleV2::drawSelf(GLFWwindow* window){
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(mProgram);
    glBindVertexArray(VAO);
    float time = glfwGetTime();
    float colorValue = sin(time) / 2.0f + 0.5f;

    int location = glGetUniformLocation(mProgram, "ourColor");
    glUniform4f(location, 0.0f, colorValue, 0.0f, 1.0f);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glfwSwapBuffers(window);
}

void TriangleV2::destroy(){
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
}
